home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / stub / go32-v2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-19  |  5.5 KB  |  217 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. /* GO32V2 - A quick hack for loading non-stubbed images for V2.0
  3.    Charles Sandmann 6/95 NO WARRANTY - build with -ldbg
  4.    Bugs: can't handle V1 images (do this someday)
  5.          doesn't scan manifest for versions installed yet */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12. #include <process.h>
  13. #include <go32.h>
  14. #include <errno.h>
  15. #include <dpmi.h>
  16. #include <debug/v2load.h>
  17.  
  18. /*======================================================================*/
  19.  
  20. #define IMG_ERROR    0
  21. #define IMG_EXE        1
  22. #define IMG_COFF    2
  23. #define IMG_V2        4
  24. #define IMG_UNKNOWN    8
  25.  
  26. #define IMG_PLAIN_EXE    (IMG_EXE | IMG_UNKNOWN)
  27. #define IMG_EXE_V1    (IMG_EXE | IMG_COFF)
  28. #define IMG_EXE_V2    (IMG_EXE | IMG_COFF | IMG_V2)
  29. #define IMG_COFF_V1    (IMG_COFF)
  30. #define IMG_COFF_V2    (IMG_COFF | IMG_V2)
  31.  
  32. /* Read the given file and determine what kind of program it is */
  33.  
  34. static int
  35. check_image_version(char *image)
  36. {
  37.   int rv = 0;
  38.   unsigned short header[3];
  39.   unsigned char firstbytes[1];
  40.   unsigned long coffhdr[42];
  41.   int pf, i;
  42.   int coff_offset, text_foffset;
  43.  
  44.   pf = open(image, O_RDONLY|O_BINARY);
  45.   if(pf < 0)
  46.   {
  47.     return IMG_ERROR;
  48.   }
  49.  
  50.   /* See if it has an EXE header */
  51.   read(pf, header, sizeof(header));
  52.   if (header[0] == 0x5a4d)    /* MZ exe signature, stubbed? */
  53.   {
  54.     coff_offset = (long)header[2]*512L;
  55.     if (header[1])
  56.       coff_offset += (long)header[1] - 512L;
  57.     lseek(pf, coff_offset, 0);
  58.     read(pf, header, sizeof(header));
  59.     rv |= IMG_EXE;
  60.   }
  61.   else
  62.     coff_offset = 0;
  63.  
  64.   /* See if it has a COFF header (maybe after exe) */
  65.   if (header[0] != 0x014c)    /* COFF? */
  66.   {
  67.     close(pf);
  68.     return rv | IMG_UNKNOWN;
  69.   }
  70.   rv |= IMG_COFF;
  71.  
  72.   /* Read the COFF header */
  73.   lseek(pf, coff_offset, 0);
  74.   i = read(pf, coffhdr, 0x0a8);    
  75.   if (i != 0x0a8)
  76.   {
  77.     close(pf);
  78.     return rv | IMG_UNKNOWN;
  79.   }
  80.  
  81.   /* See what the first opcode is */
  82.   text_foffset = coff_offset + coffhdr[12 + 5];    /* scnptr */
  83.   lseek(pf, text_foffset, 0);
  84.   read(pf, firstbytes, 1);
  85.   if (firstbytes[0] == 0xa3)    /* Opcode for movl %eax, 0x12345678 (V1) */
  86.   {
  87.     close(pf);
  88.     return rv;
  89.   }
  90.   return rv | IMG_V2;
  91. }
  92.  
  93. /*======================================================================*/
  94.  
  95. extern char **environ;
  96.  
  97. /* We were called when the V1 go32 should have been called.  Call it
  98.    with the same arguments we were passed */
  99.  
  100. void
  101. run_v1_coff(int argc, char **argv)
  102. {
  103.   char *path = getenv("PATH");
  104.   char *tokbuf = alloca(strlen(path)+1);
  105.   char *dir;
  106.  
  107.   strcpy(tokbuf, path);
  108.  
  109.   /* we don't check "." because if v1's go32 was in "." we
  110.      would never get a chance to run. */
  111.   for (dir=strtok(tokbuf, ";"); dir; dir=strtok(0, ";"))
  112.   {
  113.     char *cp;
  114.     char tmp[500];
  115.     strcpy(tmp, dir);
  116.     cp = tmp + strlen(tmp) - 1;
  117.     if (*cp != ':' && *cp != '/' && *cp != '\\')
  118.       *++cp = '/';
  119.     strcpy(cp+1, "go32.exe");
  120.     if (check_image_version(tmp) == IMG_PLAIN_EXE)
  121.     {
  122.       char oldcmdline[128];
  123.       dosmemget(_go32_info_block.linear_address_of_original_psp+128, 128, oldcmdline);
  124.       oldcmdline[1+oldcmdline[0]] = 0;
  125.       exit(_dos_exec(tmp, oldcmdline+2, environ));
  126.     }
  127.   }
  128.   fprintf(stderr, "go32/v1: cannot find v1's go32.exe\n");
  129.   exit(1);
  130. }
  131.  
  132. /*======================================================================*/
  133.  
  134. /* It was an unstubbed V2 COFF file.  Use v2load to run it */
  135.  
  136. run_v2_coff(int argc, char **argv)
  137. {
  138.   int i;
  139.   char cmdline[128];
  140.   jmp_buf start_state;
  141.  
  142.   cmdline[1] = 0;
  143.   for(i=2; argv[i]; i++)
  144.   {
  145.     strcat(cmdline+1, " ");
  146.     strcat(cmdline+1, argv[i]);
  147.   }
  148.   i = strlen(cmdline+1);
  149.   cmdline[0] = i;
  150.   cmdline[i+1] = 13;
  151.   if(v2loadimage(argv[1],cmdline,start_state))
  152.   {
  153.     fprintf(stderr, "Load failed for image %s\n",argv[1]);
  154.     exit(1);
  155.   }
  156.  
  157.   longjmp(start_state, 0);
  158.   return 0;
  159. }
  160.  
  161. /*======================================================================*/
  162.  
  163. /* Save on space, don't mess with command line */
  164. char **__crt0_glob_function(char *argument) { return 0; }
  165. void __crt0_load_environment_file(char *app) {}
  166.  
  167. int
  168. main(int argc, char **argv)
  169. {
  170.   int i;
  171.  
  172.   __djgpp_set_ctrl_c(0);
  173.  
  174.   /* called from stub, our argv[0] is toast from the !proxy */
  175.   if (check_image_version(argv[0]) != IMG_EXE_V2
  176.       || (argc > 1 &&
  177.       (strcmp(argv[1], "!proxy") == 0 || strcmp(argv[1], "-d") == 0)))
  178.   {
  179.     /* meant to run other go32 */
  180.     run_v1_coff(argc, argv);
  181.   }
  182.  
  183.   if (argc < 2)
  184.   {
  185.     printf("go32/v2 version %s built %s %s\n","2.0",__DATE__,__TIME__);
  186.     printf("Usage: go32 coff-image [args]\n");
  187.     printf("Rename this to go32.exe only if you need a go32 that can run v2 binaries as\n"
  188.        " well as v1 binaries (old makefiles).  Put ahead of the old go32 in your PATH.\n");
  189.     i = _go32_dpmi_remaining_physical_memory()/1024;
  190.     printf("DPMI memory available: %d Kb\n",i);
  191.     i = _go32_dpmi_remaining_virtual_memory()/1024-i;
  192.     if(i < 0)
  193.       i = 0;
  194.     printf("DPMI swap space available: %d Kb\n", i);
  195.     exit(1);
  196.   }
  197.  
  198.   switch (check_image_version(argv[1]))
  199.   {
  200.   case IMG_UNKNOWN:
  201.     fprintf(stderr, "go32/v2: Unknown file type: %s\n", argv[1]);
  202.     exit(1);
  203.   case IMG_ERROR:
  204.     fprintf(stderr, "go32/v2: Error: %s: \n", argv[1], strerror(errno));
  205.     exit(1);
  206.   case IMG_COFF_V2:
  207.     run_v2_coff(argc, argv);
  208.   case IMG_COFF_V1:
  209.   case IMG_EXE_V1:
  210.     run_v1_coff(argc, argv);
  211.   case IMG_PLAIN_EXE:
  212.   case IMG_EXE_V2:
  213.     return spawnv(P_WAIT, argv[1], argv+1);
  214.   }
  215.   exit(1);
  216. }
  217.